home *** CD-ROM | disk | FTP | other *** search
/ 9-Digit Zip Code Directory / 9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO / z4src.zip / BSPRINT.C < prev    next >
C/C++ Source or Header  |  1995-09-12  |  25KB  |  855 lines

  1. //----------------------------------------------------------------------------
  2. //                            MODULE DESCRIPTION
  3. //
  4. //  Module:    bsprint.c
  5. //   Title:    Base library
  6. //  Notice:    John M. Weeder
  7. //                 Copyright (c) 1993. All rights reserved.
  8. //             This module contains proprietary information and should be 
  9. //                treated as confidential.
  10. //
  11. //----------------------------------------------------------------------------
  12. //                           MAINTENANCE HISTORY
  13. //
  14. // $Workfile$
  15. // $Revision$
  16. //   $Author$
  17. //     $Date$
  18. //      $Log$    
  19. //
  20. //----------------------------------------------------------------------------
  21. //                             MODULE NARRATIVE
  22. //
  23. //
  24. //    This module contains code to print a text file to the printer output 
  25. //    device for the current operating system.
  26. //
  27. //    The input text file must contain ASCII printable characters. Control 
  28. //    strings are inserted using the <ESC> (27 or 0x1B). Control string must 
  29. //    begin and end with an escape character. Control strings are also terminated
  30. //    at the end of a line. If a control string ends at the end of a line but
  31. //    does not have a terminating <ESC> character, then the line feed is 
  32. //    suppressed.
  33. //    The control string consists of a command followed by an optional equal
  34. //     ('=') sign and the command arguments.
  35. //    For example:
  36. //        <ESC>command=arguments<ESC>
  37. //
  38. //    The following commands are currently recognized:
  39. //
  40. //    The following commands are planned for implementation:
  41. //        TABS = nn nn nn nn                    Tab stops
  42. //                                                    Tab stops are printer and OS dependent.
  43. //        FOOTER = footer text                    Header
  44. //        HEADER = header text                    Footer
  45. //                                                    Both the header and the footer may
  46. //                                                    contain option codes to fill in the
  47. //                                                    date/time/page.
  48. //                                                        &p        Page Number
  49. //                                                        &d        Date
  50. //                                                        &t        Time
  51. //
  52. //    Form feeds are recognized and converted into automatic page breaks.
  53. //    Tabs are recognized and converted according to the current tab stop
  54. //    settings.
  55. //
  56. //    Line length (including control characters) must not exceed MAX_PRINT_BUF
  57. //    characters.
  58. //
  59. //    The windows version of this module expects to find a dialog resource 
  60. //    named 'AbortPrintDlg'
  61. //
  62. //    This module is not re-entrant and cannot be used in a multi-thread
  63. //    environment.
  64. //    
  65. //
  66. //    The code in this module should be written entirely in C. 
  67. //    Do not use any C++ constructs.
  68. //
  69. //    This module is portable to:
  70. //        DOS 3.X+
  71. //        MS Windows 3.X+
  72. //        OS/2 2.X+
  73. //        OS/2 2.0 PM
  74. //        SCO UNIX.
  75. //
  76. //    The following compilers are supported:
  77. //        MSC 6.0A
  78. //        MSC/C++ 7.0
  79. //        Borland C++ 3.1 for DOS
  80. //        Borland C++ 1.0 for OS/2 2.X
  81. //        SCO UNIX cc
  82. //
  83. //----------------------------------------------------------------------------
  84. #include <bs.h>
  85.  
  86.  
  87. //----------------------------------------------------------------------------
  88. //    Constants
  89. //----------------------------------------------------------------------------
  90. #if OS_DOS || OS_WINDOWS
  91. #define MAX_PRINT_BUF        (2048)
  92. #define MAX_TABS                (20)
  93. typedef struct PRT                            // Globals for printer routines
  94. {
  95.     FLAG16 fs;                                    // Flags
  96.     PFNPRINT pfnprint;                        // Printer callback function
  97.     PCSZ pcszName;                                // Print job name
  98.  
  99.     USHORT usPort;                                // Printer port (DOS only)
  100.     BOOL fCommandPending;                    // Escape command pending
  101.     BOOL fCRPending;                            // Carriage return pending
  102.     BOOL fAbort;                                // Abort flag
  103.  
  104.     CHAR szFile[MAX_PATH];                    // Spool file name
  105.     HF hf;                                        // Input file handle
  106.     //LONG lSize;                                    // Input file length
  107.     ULONG lSize;
  108.     FPOS fpos;                                    // Current position in input file
  109.     BOOL fError;                                // Error flag
  110.  
  111.     BYTE bBuf1[MAX_PRINT_BUF+1];            // Input buffer
  112.     PBYTE pb1;                                    // Next character to use in buffer
  113.     SIZET cBuf1;                                // Amount of data in buffer
  114.     BYTE bBuf2[MAX_PRINT_BUF+1];            //    Output for current line of text
  115.     PBYTE pb2;                                    // Next character to use in buffer
  116.     BYTE bBuf3[MAX_PRINT_BUF+1];            //    Output for current command
  117.     PBYTE pb3;                                    // Next character to use in buffer
  118.  
  119. #if OS_WINDOWS
  120.     PRINTDLG pd;                                // Print dialog data
  121.    HWND hAbortDlgWnd;                        // Cancel dialog handle
  122.     DLGPROC lpAbortDlg;                        // Cancel dialog procedure
  123.     FARPROC lpAbortProc;                        // Printing abort procedure
  124.    HANDLE hHourGlass;                      // Hour glass cursor
  125.    HANDLE hSaveCursor;                        // Current cursor handle
  126.    HDC hPr;                                        // Handle for printer device context
  127.    TEXTMETRIC textmetric;                    // Information about character size
  128.     INT iLineSpace;                            // Spacing between lines
  129.     INT iHorzSize;                                // Horizaontal page size
  130.     INT iVertSize;                                // Vertical page size
  131.     INT iTop;                                    // Top of next line
  132.     INT iStatus;                                // Printer status
  133.     BOOL fPagePending;
  134. #endif
  135.  
  136. } PRT;
  137. BASETYPE(PRT);
  138. #endif
  139.  
  140. //----------------------------------------------------------------------------
  141. //    Globals
  142. //----------------------------------------------------------------------------
  143. #if OS_DOS || OS_WINDOWS
  144. static PPRT _pprt = NULL;
  145. #endif
  146.  
  147. //----------------------------------------------------------------------------
  148. //    Prototypes
  149. //----------------------------------------------------------------------------
  150. #if OS_DOS
  151. static USHORT FN_E DosPrintStatus(USHORT);
  152. static BOOL FN_E PrintFFDos(PPRT);
  153. static BOOL FN_E PrintTextDos(PPRT);
  154. #endif
  155.  
  156. #if OS_DOS || OS_WINDOWS
  157. static BOOL FN_E PrintBuffer(PPRT);
  158. static BOOL FN_E PrintCommand(PPRT);
  159. static PPRT FN_E PrintInitialize(PCSZ, FLAG16, PFNPRINT, PCSZ);
  160. static BOOL FN_E PrintProcess(PPRT);
  161. static BOOL FN_E PrintTerminate(PPRT);
  162. static BOOL FN_E PrintText(PPRT, BOOL);
  163. #endif
  164.  
  165. #if OS_WINDOWS
  166. static BOOL FN_E PrintFFWindows(PPRT);
  167. static BOOL FN_E PrintTextWindows(PPRT);
  168. static int FN_W WindowsAbortDlg(HWND, unsigned, WORD, LONG);
  169. static int FN_W WindowsAbortProc(HDC, int);
  170. static HDC FN_L WindowsGetPrinterDC(PPRT);
  171. #endif
  172.  
  173.  
  174. //----------------------------------------------------------------------------
  175. //   Description:    Print a single line.
  176. //                          This function is not valid under Windows!
  177. //    Parameters:    pcsz    Line to print.
  178. //                                If null, return status.
  179. //       Returns:
  180. //----------------------------------------------------------------------------
  181. #if OS_DOS
  182. USHORT FN_E DosPrintLine(PCSZ pcsz, USHORT usPort)
  183. {
  184.     USHORT usStatus = 0;
  185.  
  186.     usStatus = DosPrintStatus(_bios_printer(_PRINTER_STATUS, usPort, 0));
  187.     if (pcsz != NULL)
  188.         {
  189.         while (pcsz[0] && usStatus == 0)
  190.             {
  191.             usStatus = DosPrintStatus(_bios_printer(_PRINTER_WRITE, usPort, pcsz[0]));
  192.             pcsz++;
  193.             }
  194.         }
  195.     return usStatus;
  196. }
  197. #endif
  198.  
  199.  
  200. //----------------------------------------------------------------------------
  201. //   Description:    Print a file
  202. //    Parameters:    pcsz    Line to print.
  203. //                                If null, return status.
  204. //       Returns:    
  205. //----------------------------------------------------------------------------
  206. #if OS_DOS
  207. static USHORT FN_E DosPrintStatus(USHORT usStatus)
  208. {
  209.     usStatus &= ~(PRT_ERR_NO_ACK|PRT_ERR_BUSY);
  210.     return usStatus ^ PRT_ERR_NOT_SELECTED;
  211. }
  212. #endif
  213.  
  214.  
  215.  
  216. //----------------------------------------------------------------------------
  217. //   Description:    
  218. //    Parameters:    
  219. //       Returns:    TRUE if successful.
  220. //----------------------------------------------------------------------------
  221. #if OS_DOS || OS_WINDOWS
  222. static BOOL FN_E PrintBuffer(PPRT pprt)
  223. {
  224.     pprt->pb1 = pprt->bBuf1;                // Setup pointer to buffer
  225.     for (; (SIZET)(pprt->pb1 - pprt->bBuf1) < pprt->cBuf1 && !pprt->fAbort; ++pprt->pb1)
  226.         {
  227.         if (*pprt->pb1 == PRT_ESCAPE)        // Printer escape
  228.             {
  229.             if (pprt->fCommandPending)        // If command is pending, process it
  230.                 {
  231.                 if (!PrintCommand(pprt))
  232.                     return FALSE;
  233.                 }
  234.             else                                    // Else, start a new command
  235.                 pprt->fCommandPending = TRUE;
  236.             }
  237.         else if (*pprt->pb1 == '\t')        // Tab
  238.             {
  239.             Assert((SIZET)(pprt->pb3 - pprt->bBuf3) < MAX_PRINT_BUF);
  240.             *pprt->pb3++ = ' ';
  241.             }
  242.         else if (*pprt->pb1 == '\f')
  243.             {
  244.             if (pprt->fCommandPending)        // If a command is pending, process it
  245.                 if (!PrintCommand(pprt))
  246.                     return FALSE;
  247.             if (!PrintText(pprt, FALSE))    // Flush text on this page
  248.                 return FALSE;
  249. #if OS_DOS
  250.             if (!PrintFFDos(pprt))            // Goto next page
  251.                 return FALSE;
  252. #elif OS_WINDOWS
  253.             if (!PrintFFWindows(pprt))
  254.                 return FALSE;
  255. #endif
  256.             }
  257.         else if (*pprt->pb1 == '\r'        // End of line. Flush command buffer
  258.         || *pprt->pb1 == '\n')                //  and text buffer as needed
  259.             {
  260.             if (!pprt->fCRPending            // Make sure this is not part of a
  261.             || *pprt->pb1 == '\r')            // CR/LF sequence in a DOS file
  262.                 {
  263.                 if (pprt->fCommandPending)    // If a command is pending, process it
  264.                     {                                //  and suppress line feed
  265.                     if (!PrintCommand(pprt))
  266.                         return FALSE;
  267.                     }                                // Process any text
  268.                 else if (!PrintText(pprt, TRUE))
  269.                     return FALSE;
  270.                 }
  271.             }
  272.         else if (iscntrl(*pprt->pb1))        // Other control character?
  273.             {
  274.             ;                                        // Ignore character
  275.             }
  276.         else if (pprt->fCommandPending)    // Append byte to command buffer
  277.             {
  278.             Assert((SIZET)(pprt->pb3 - pprt->bBuf3) < MAX_PRINT_BUF);
  279.             *pprt->pb3++ = *pprt->pb1;
  280.             }
  281.         else                                        // Append byte to text buffer
  282.             {
  283.             Assert((SIZET)(pprt->pb2 - pprt->bBuf2) < MAX_PRINT_BUF);
  284.             *pprt->pb2++ = *pprt->pb1;
  285.             }
  286.         pprt->fCRPending = (*pprt->pb1 == '\r');
  287.         }
  288.     return TRUE;
  289. }
  290. #endif
  291.  
  292. //----------------------------------------------------------------------------
  293. //   Description:
  294. //    Parameters:
  295. //       Returns:    TRUE if successful.
  296. //----------------------------------------------------------------------------
  297. #if OS_DOS || OS_WINDOWS
  298. static BOOL FN_E PrintCommand(PPRT pprt)
  299. {
  300. static PCSZ apcsz[] =                        // List of valid commands
  301.     {
  302.     "command",
  303.     NULL
  304.     };
  305.     PSZ psz1, psz2;
  306.     SIZET i;
  307.  
  308.     *pprt->pb3 = '\0';                        // Add a null terminator to the buffer
  309.  
  310.     psz1 = (PSZ)pprt->bBuf3;
  311.     psz2 = strchr(psz1, '=');
  312.     if (psz2 != NULL)
  313.         {
  314.         *psz2 = '\0';                            // Replace '=' with a null and point
  315.         psz2++;                                    //  to the arguments
  316.         }
  317.     else
  318.         psz2 = "";                                // No arguments
  319.  
  320.     strtrim(psz1);                                // Clean up the string
  321.     for (i = 0; apcsz[i]; ++i)                // Find command
  322.         if (stricmp(psz1, apcsz[i]) == 0)
  323.             break;
  324.  
  325.     switch (i)
  326.         {
  327.         case 0:
  328.             break;
  329.  
  330.         default:                                    // Invalid
  331.             Log(LOG_LOW, "Invalid print spool command, '%s'.", psz1);
  332.             break;
  333.         }
  334.     pprt->fCommandPending = FALSE;        // Reset for next command
  335.     pprt->pb3 = pprt->bBuf3;
  336.     return TRUE;
  337. }
  338. #endif
  339.  
  340. //----------------------------------------------------------------------------
  341. //   Description:    Print a file.
  342. //    Parameters:    pcszFile        Name of file to print.
  343. //                                        File is searched for in the directories 
  344. //                                        specified by the 'TEMP' environment variable.
  345. //                                        Default extension is PRN
  346. //                        fs                Flags:
  347. //                                            See header file (bsproto.h)
  348. //                        pfnprint        Printer callback function.
  349. //                                        This function takes a single parameter which is
  350. //                                        the current printer error.
  351. //                                        This function should return TRUE to continue 
  352. //                                        printing or FALSE to abort.
  353. //                        pcszName        Print job name or NULL
  354. //       Returns:    TRUE if successful.
  355. //----------------------------------------------------------------------------
  356. BOOL FN_E PrintFile(PCSZ pcszFile, FLAG16 fs, PFNPRINT pfnprint, PCSZ pcszName)
  357. {
  358. #if OS_DOS || OS_WINDOWS
  359.  
  360.     PPRT pprt;
  361.  
  362.     if (pcszFile == NULL || !pcszFile[0])
  363.         return TRUE;
  364.                                                     // Initialize for printing
  365.     pprt = PrintInitialize(pcszFile, fs, pfnprint, pcszName);
  366.     if (pprt == NULL)
  367.         return FALSE;
  368.  
  369.     if (!pprt->fError)                        // Process file
  370.         PrintProcess(pprt);
  371.  
  372.     return PrintTerminate(pprt);            // Clean up
  373.  
  374. #else
  375.  
  376.     NOTUSED(fs);
  377.     NOTUSED(pcszFile);
  378.     NOTUSED(pfnprint);
  379.     NOTUSED(pcszName);
  380.     return FALSE;
  381.  
  382. #endif
  383. }
  384.  
  385.  
  386. //----------------------------------------------------------------------------
  387. //   Description:
  388. //    Parameters:
  389. //       Returns:    TRUE if successful.
  390. //----------------------------------------------------------------------------
  391. #if OS_DOS || OS_WINDOWS
  392. static PPRT FN_E PrintInitialize(PCSZ pcszFile, FLAG16 fs, PFNPRINT pfnprint, PCSZ pcszName)
  393. {
  394.     PPRT pprt;
  395.     FLAG16 fsFile;
  396.  
  397.  
  398.     //
  399.     //    Allocate space for globals
  400.     //
  401.     pprt = (PPRT)MemAllocZero(sizeof(PRT));
  402.     if (pprt == NULL)
  403.         {
  404.         ErrorNoMem();
  405.         return NULL;
  406.         }
  407.     //
  408.     //    Initialize variables
  409.     //
  410.     pprt->fs = fs;
  411.     pprt->pfnprint = pfnprint;
  412.     pprt->hf = -1;
  413.     pprt->pcszName = pcszName ? pcszName: "unknown";
  414.  
  415.     if (BTEST(pprt->fs, PRT_LPT2))
  416.         pprt->usPort = 1;
  417.     else if (BTEST(pprt->fs, PRT_LPT3))
  418.         pprt->usPort = 2;
  419.     else if (BTEST(pprt->fs, PRT_LPT4))
  420.         pprt->usPort = 3;
  421.  
  422.     //
  423.     //    Store windows globals
  424.     //
  425. #if OS_WINDOWS
  426.    pprt->hHourGlass = LoadCursor(NULL, IDC_WAIT);
  427.     pprt->hSaveCursor = SetCursor(pprt->hHourGlass);
  428.  
  429.    pprt->pd.lStructSize = sizeof(PRINTDLG);
  430.    pprt->pd.hwndOwner   = NULL;
  431.    pprt->pd.hDevMode    = NULL;
  432.    pprt->pd.hDevNames   = NULL;
  433.     pprt->pd.Flags       = (DWORD)(PD_RETURNDC|PD_NOSELECTION|PD_NOPAGENUMS|PD_USEDEVMODECOPIES);
  434.    pprt->pd.nCopies     = 1;
  435.  
  436.     pprt->hPr = WindowsGetPrinterDC(pprt);
  437.    if (!pprt->hPr)
  438.         goto ERROR_EXIT;
  439.  
  440. #if COMPILE_DLL
  441.     pprt->lpAbortDlg =  (DLGPROC)WindowsAbortDlg;
  442.     pprt->lpAbortProc = (FARPROC)WindowsAbortProc;
  443. #else
  444.     pprt->lpAbortDlg =  (DLGPROC)MakeProcInstance((FARPROC)WindowsAbortDlg, WindowsInstance());
  445.     pprt->lpAbortProc = MakeProcInstance((FARPROC)WindowsAbortProc, WindowsInstance());
  446. #endif
  447.  
  448.     Escape(pprt->hPr, SETABORTPROC, 0, (LPSTR)pprt->lpAbortProc, (LPSTR)NULL);
  449.     if (Escape(pprt->hPr, STARTDOC, strlen(pprt->pcszName) + 1, pprt->pcszName, (LPSTR)NULL) < 0)
  450.         goto ERROR_EXIT;
  451.                                                     // Create the Abort dialog box (modeless)
  452.     pprt->hAbortDlgWnd = CreateDialog(WindowsInstance(), "AbortPrintDlg", GetActiveWindow(), pprt->lpAbortDlg);
  453.     if (!pprt->hAbortDlgWnd)
  454.         goto ERROR_EXIT;
  455.                                                     // Now show Abort dialog
  456.     ShowWindow (pprt->hAbortDlgWnd, SW_NORMAL);
  457.  
  458.     SetCursor(pprt->hSaveCursor);          // Remove the hourglass
  459.     pprt->hSaveCursor = 0;
  460.  
  461.     GetTextMetrics(pprt->hPr, &pprt->textmetric);
  462.     pprt->iLineSpace = pprt->textmetric.tmHeight + pprt->textmetric.tmExternalLeading;
  463.       pprt->iHorzSize = GetDeviceCaps (pprt->hPr, HORZRES);
  464.       pprt->iVertSize = GetDeviceCaps (pprt->hPr, VERTRES);
  465.  
  466. #endif
  467.  
  468.     //
  469.     //    Open the input file
  470.     //
  471.     strcpy(pprt->szFile, pcszFile);
  472.     if (!FnameQualify(pprt->szFile, "PRN", EnvGet("TEMP"), FNAME_APP_DIR|FNAME_NO_CREATE)
  473.     || !FnameIsFile(pprt->szFile))
  474.         {
  475.         Error("Print spool file '%s' not found.", pcszFile);
  476.         goto ERROR_EXIT;
  477.         }
  478.     fsFile = FL_OPEN|FL_READONLY|FL_BINARY;
  479.     if (!FileOpen(&pprt->hf, pprt->szFile, fsFile, NULL))
  480.         {
  481.         Error("Unable to open print spool file '%s'.", pcszFile);
  482.         goto ERROR_EXIT;
  483.         }
  484.     pprt->lSize = FileGetSize(pprt->hf);
  485.     if (pprt->lSize < 0)
  486.         goto ERROR_EXIT;
  487.  
  488.     _pprt = pprt;
  489.     return pprt;
  490.  
  491. ERROR_EXIT:
  492.     pprt->fError = TRUE;
  493.     return pprt;
  494. }
  495. #endif
  496.  
  497. //----------------------------------------------------------------------------
  498. //   Description:    Process print file
  499. //    Parameters:
  500. //       Returns:    TRUE if successful.
  501. //----------------------------------------------------------------------------
  502. #if OS_DOS || OS_WINDOWS
  503. static BOOL FN_E PrintProcess(PPRT pprt)
  504. {
  505.     pprt->pb2 = pprt->bBuf2;                // Set pointers to output buffers
  506.     pprt->pb3 = pprt->bBuf3;                
  507.     while ((unsigned)pprt->fpos < pprt->lSize && !pprt->fAbort)
  508.         {                                            // Read a full buffer
  509.         pprt->cBuf1 = (SIZET)MIN((FPOS)MAX_PRINT_BUF, (FPOS)(pprt->lSize - pprt->fpos));
  510.         if (!FileRead(pprt->hf, pprt->bBuf1, pprt->cBuf1, pprt->fpos))
  511.             {
  512.             pprt->fError = TRUE;
  513.             break;
  514.             }
  515.         if (!PrintBuffer(pprt))             // Process this buffer
  516.             break;
  517.         pprt->fpos += (FPOS)pprt->cBuf1;    // Move to start of next buffer
  518.         }
  519.     if (pprt->fCommandPending)                // If a command is pending, process it
  520.         PrintCommand(pprt);
  521.     PrintText(pprt, FALSE);                    // Process any remaining text
  522.     return pprt->fError ?  FALSE: TRUE;
  523. }
  524. #endif
  525.  
  526. //----------------------------------------------------------------------------
  527. //   Description:
  528. //    Parameters:
  529. //       Returns:    TRUE if successful.
  530. //----------------------------------------------------------------------------
  531. #if OS_DOS || OS_WINDOWS
  532. static BOOL FN_E PrintTerminate(PPRT pprt)
  533. {
  534.     BOOL fError = pprt->fError;
  535.     if (fError)
  536.         Log(LOG_LOW, "'%s' printed successfully.", pprt->szFile);
  537.     else
  538.         Log(LOG_LOW, "'%s' printing failed.", pprt->szFile);
  539.  
  540.     if (pprt->hf >= 0)                        // Close input file
  541.         FileClose(pprt->hf);
  542.                                                     // Delete spool file
  543.     if (BTEST(pprt->fs, PRT_DELETE_SPOOL))
  544.         FnameDelete(pprt->szFile);
  545.  
  546. #if OS_WINDOWS
  547.    if (pprt->iStatus >= 0                    // Flush last page!
  548.     && pprt->fPagePending
  549.     && !pprt->fAbort)
  550.         Escape(pprt->hPr, NEWFRAME, 0, 0L, 0L);
  551.     if (pprt->hPr)
  552.         {
  553.         Escape(pprt->hPr, ENDDOC, 0, 0L, 0L);
  554.         DeleteDC(pprt->hPr);
  555.         }
  556.     if (pprt->hAbortDlgWnd)
  557.         DestroyWindow(pprt->hAbortDlgWnd);
  558.     if (pprt->lpAbortDlg)
  559.         FreeProcInstance((FARPROC)pprt->lpAbortDlg);
  560.     if (pprt->lpAbortProc)
  561.       FreeProcInstance(pprt->lpAbortProc);
  562.     if (pprt->hSaveCursor)
  563.       SetCursor(pprt->hSaveCursor);        // Remove the hourglass
  564. #else 
  565.     if (!PrintFFDos(pprt))                    // Goto next page
  566.         return FALSE;
  567. #endif
  568.  
  569.     MemFree(pprt);
  570.     _pprt = NULL;
  571.     return fError ? FALSE: TRUE;
  572. }
  573. #endif
  574.  
  575. //----------------------------------------------------------------------------
  576. //   Description:
  577. //    Parameters:
  578. //       Returns:    TRUE if successful.
  579. //----------------------------------------------------------------------------
  580. #if OS_DOS || OS_WINDOWS
  581. static BOOL FN_E PrintText(PPRT pprt, BOOL fLf)
  582. {
  583.     PSZ psz1;
  584.  
  585.     *pprt->pb2 = '\0';                        // Add null terminator
  586.     psz1 = (PSZ)pprt->bBuf2;
  587.     if (fLf || psz1[0])                        // If forced linefeed or text pending
  588.         {
  589. #if OS_DOS
  590.         if (!PrintTextDos(pprt))
  591.             return FALSE;
  592. #elif OS_WINDOWS
  593.         if (!PrintTextWindows(pprt))
  594.             return FALSE;
  595. #endif
  596.         }
  597.     pprt->pb2 = pprt->bBuf2;
  598.     return TRUE;
  599. }
  600. #endif
  601.  
  602. //----------------------------------------------------------------------------
  603. //   Description:    Print a buffer of text under DOS
  604. //    Parameters:    
  605. //       Returns:    TRUE if successful.
  606. //----------------------------------------------------------------------------
  607. #if OS_DOS
  608. static BOOL FN_E PrintFFDos(PPRT pprt)
  609. {
  610.     USHORT us1;
  611.     
  612.     us1 = DosPrintLine("\f", pprt->usPort);
  613.     if (us1)
  614.         {
  615.         pprt->fError = TRUE;
  616.         return FALSE;
  617.         }
  618.     return TRUE;
  619. }
  620. #endif
  621.  
  622.  
  623. //----------------------------------------------------------------------------
  624. //   Description:    Print a buffer of text under DOS
  625. //    Parameters:    
  626. //       Returns:    TRUE if successful.
  627. //----------------------------------------------------------------------------
  628. #if OS_DOS
  629. static BOOL FN_E PrintTextDos(PPRT pprt)
  630. {
  631.     USHORT us1, us2;
  632.     
  633.     us1 = DosPrintLine((PSZ)pprt->bBuf2, pprt->usPort);
  634.     us2 = DosPrintLine("\r\n", pprt->usPort);
  635.     if (us1 || us2)
  636.         {
  637.         pprt->fError = TRUE;
  638.         return FALSE;
  639.         }
  640.     return TRUE;
  641. }
  642. #endif
  643.  
  644.  
  645. //----------------------------------------------------------------------------
  646. //   Description:    
  647. //    Parameters:    
  648. //       Returns:    TRUE if successful.
  649. //----------------------------------------------------------------------------
  650. #if OS_WINDOWS
  651. static BOOL FN_E PrintFFWindows(PPRT pprt)
  652. {
  653.    if (pprt->iStatus >= 0                // Flush current page
  654.     && !pprt->fAbort)
  655.        pprt->iStatus = Escape(pprt->hPr, NEWFRAME, 0, 0L, 0L);
  656.  
  657.     pprt->fPagePending = FALSE;
  658.     return TRUE;
  659. }
  660. #endif
  661.  
  662.  
  663. //----------------------------------------------------------------------------
  664. //   Description:    
  665. //    Parameters:    
  666. //       Returns:    TRUE if successful.
  667. //----------------------------------------------------------------------------
  668. #if OS_WINDOWS
  669. static BOOL FN_E PrintTextWindows(PPRT pprt)
  670. {
  671.     PSZ psz1 = (PSZ)pprt->bBuf2;
  672.     RECT rect;
  673.     INT iHeight;
  674.     WORD wFlags;
  675.  
  676.  
  677.     rect.left = 0;
  678.     rect.top = pprt->iTop;
  679.     rect.right = pprt->iHorzSize - 1;
  680.     rect.bottom = pprt->iVertSize - pprt->iTop - 1;
  681.     wFlags = DT_LEFT|DT_EXPANDTABS|DT_NOPREFIX|DT_WORDBREAK;
  682.     iHeight = DrawText(pprt->hPr, psz1, -1, &rect, wFlags|DT_CALCRECT);
  683.  
  684.     if (pprt->iTop && 
  685.     iHeight > pprt->iVertSize - pprt->iTop - 1)
  686.         {
  687.       if (pprt->iStatus >= 0                // Flush current page
  688.         && !pprt->fAbort)
  689.            pprt->iStatus = Escape(pprt->hPr, NEWFRAME, 0, 0L, 0L);
  690.  
  691.         pprt->iTop = 0;                        // Recurse 1 level
  692.         return PrintTextWindows(pprt);
  693.         }
  694.     if (pprt->iStatus < 0)
  695.         pprt->fError = TRUE;
  696.  
  697.     pprt->fPagePending = TRUE;
  698.     DrawText(pprt->hPr, psz1, -1, &rect, wFlags); 
  699.     pprt->iTop += iHeight;
  700.     return !pprt->fError;
  701. }
  702. #endif
  703.  
  704.  
  705. //----------------------------------------------------------------------------
  706. //   Description:    
  707. //    Parameters:
  708. //       Returns:    TRUE if successful.
  709. //----------------------------------------------------------------------------
  710. #if OS_WINDOWS
  711. static int FN_W WindowsAbortDlg(HWND hDlg, unsigned msg, WORD wParam, LONG lParam)
  712. {
  713.     NOTUSED(wParam);
  714.    NOTUSED(lParam);
  715.    switch(msg)
  716.         {                                            
  717.       case WM_COMMAND:                        // Watch for Cancel button, RETURN key,
  718.             if (_pprt)                            //  ESCAPE key, or SPACE BAR
  719.                 _pprt->fAbort = TRUE;
  720.             return TRUE;
  721.  
  722.         case WM_INITDIALOG:                    // Set the focus to the Cancel box of the dialog
  723.           {
  724.             RECT rectDesk, rect;                // Center the dialog
  725.             INT x, y, cx, cy;
  726.  
  727.             GetWindowRect(GetDesktopWindow(), &rectDesk);
  728.             GetWindowRect(hDlg, &rect);
  729.  
  730.             cx = rect.right - rect.left + 1;
  731.             cy = rect.bottom - rect.top + 1;
  732.             x = ((rectDesk.right - rectDesk.left + 1) - cx) / 2;
  733.             y = ((rectDesk.bottom - rectDesk.top + 1) - cy) / 2;
  734.  
  735.             SetWindowPos(hDlg, (HWND)NULL, x, y,  cx, cy, SWP_NOZORDER|SWP_NOACTIVATE);
  736.                                                     // Set focus to cancel button
  737.             SetFocus(GetDlgItem(hDlg, IDCANCEL));
  738.          }
  739.          return TRUE;
  740.       }
  741.    return FALSE;
  742. }
  743. #endif
  744.  
  745.  
  746. //----------------------------------------------------------------------------
  747. //   Description:    
  748. //    Parameters:
  749. //       Returns:    TRUE if successful.
  750. //----------------------------------------------------------------------------
  751. #if OS_WINDOWS
  752. static int FN_W WindowsAbortProc(HDC hPr, int iCode)
  753. {
  754.     MSG msg;
  755.  
  756.     NOTUSED(hPr);
  757.     NOTUSED(iCode);
  758.     if (_pprt == NULL                            // If not initialized correctly
  759.     || !_pprt->hAbortDlgWnd)                // If the abort dialog isn't up yet
  760.        return TRUE;
  761.  
  762.     //
  763.     // Process messages intended for the abort dialog box
  764.     //
  765.    while (!_pprt->fAbort && PeekMessage(&msg, NULL, 0/*NULL*/, 0/*NULL*/, TRUE))
  766.         {
  767.       if (!IsDialogMessage(_pprt->hAbortDlgWnd, &msg))
  768.             {
  769.          TranslateMessage(&msg);
  770.          DispatchMessage(&msg);
  771.            }
  772.         }
  773.     return !_pprt->fAbort;                    // Has the user has aborted?
  774. }
  775. #endif
  776.  
  777.  
  778. //----------------------------------------------------------------------------
  779. //   Description:    
  780. //    Parameters:
  781. //       Returns:    
  782. //----------------------------------------------------------------------------
  783. #if OS_WINDOWS
  784. static HDC FN_L WindowsGetPrinterDC(PPRT pprt)
  785. {
  786.    HDC hDC;
  787.    LPDEVMODE lpDevMode = NULL;
  788.    LPDEVNAMES lpDevNames;
  789.    LPSTR lpszDriverName;
  790.    LPSTR lpszDeviceName;
  791.    LPSTR lpszPortName;
  792.  
  793.     if (!PrintDlg((LPPRINTDLG)&pprt->pd))
  794.       return NULL;
  795.  
  796.    if (pprt->pd.hDC)
  797.       hDC = pprt->pd.hDC;
  798.    else
  799.          {
  800.       if (!pprt->pd.hDevNames)
  801.             {
  802.             Error("No printer device found.");
  803.             pprt->fError = TRUE;
  804.          return NULL;
  805.             }
  806.       lpDevNames = (LPDEVNAMES)GlobalLock(pprt->pd.hDevNames);
  807.       lpszDriverName = (LPSTR)lpDevNames + lpDevNames->wDriverOffset;
  808.       lpszDeviceName = (LPSTR)lpDevNames + lpDevNames->wDeviceOffset;
  809.       lpszPortName   = (LPSTR)lpDevNames + lpDevNames->wOutputOffset;
  810.       GlobalUnlock(pprt->pd.hDevNames);
  811.  
  812.       if (pprt->pd.hDevMode)
  813.          lpDevMode = (LPDEVMODE)GlobalLock(pprt->pd.hDevMode);
  814.  
  815.       hDC = CreateDC(lpszDriverName, lpszDeviceName, lpszPortName, (LPSTR)lpDevMode);
  816.  
  817.       if (pprt->pd.hDevMode && lpDevMode)
  818.          GlobalUnlock(pprt->pd.hDevMode);
  819.          }
  820.    if (pprt->pd.hDevNames)
  821.         {
  822.         GlobalFree(pprt->pd.hDevNames);
  823.         pprt->pd.hDevNames = NULL;
  824.         }
  825.    if (pprt->pd.hDevMode)
  826.       {
  827.       GlobalFree(pprt->pd.hDevMode);
  828.         pprt->pd.hDevMode=NULL;
  829.       }
  830.    return hDC;
  831. }
  832. #endif
  833.  
  834.  
  835. //----------------------------------------------------------------------------
  836. //   Description:    Run standard test suite
  837. //    Parameters:    sTest        Test to run.
  838. //                                        0        Run all default tests (except).
  839. //       Returns:    TRUE if successful.
  840. //----------------------------------------------------------------------------
  841. #if COMPILE_TEST
  842. BOOL FN PrintTest(SHORT sTest)
  843. {
  844.     NOTUSED(sTest);
  845. #if OS_DOS || OS_WINDOWS
  846.     return PrintFile("\\config.sys", 0, NULL, NULL);
  847. #else
  848.     return TRUE;
  849. #endif
  850. }
  851. #endif
  852. //----------------------------------------------------------------------------
  853. //------------------------------- End of File --------------------------------
  854. //----------------------------------------------------------------------------
  855.